/*
* $Id: srf.c,v 1.59 2008/02/21 08:01:27 chunchia Exp $
*/
/*******************************************************************************

       UBEC (Uniband Electronic Corp.)

       Project: U-NET01, Ubiquitous network platform

       File: srf.c

       Version: 0.3.0

       Usage: Simple Rf Control Function

       Platform: U-NET01 DK with Keil 8051 C compiler

       Reference:

               Silicon Laboratories: C8051F124, C8051F340

               UBEC: UZ2400, UZ2410

       Note :

               Copyright (C) 2007 Uniband Electronic Corporation, All rights reserved

********************************************************************************/

#include "unet.h"

#if 0 // DEBUG_MODE
	#undef  TRACE_TAG
	#define TRACE_TAG()
	#undef  TRACE_puts
	#define TRACE_puts              DBG_puts
	#undef  TRACE_printf
	#define TRACE_printf(P)         dbg_printf P
#endif

extern UNET_SYS UnetSys;

/**************************************************************
	Function Name: reset_RF_state_machine()
	Description: Initial UZ2400 RF state machine
	Parameters: None
	Return Value: None
**************************************************************/
static void reset_RF_state_machine(void)
{
	//Reset RF state machine
	spi_sw(RFCTL, RFRESET);
	spi_sw(RFCTL, 0x00);

	// 2007/11/6 09:50, Sunny: wait until RX state
	while(spi_lr(RFSTATE) != RF_STATE_RX);
}

/**************************************************************
	Function Name: UzInit()
	Description: Initial UZ2400
	Parameters: None
	Return Value: None
**************************************************************/
void UzInit(){

	TRACE_puts("UzInit");

	UzChipReset();

	UzSoftReset();

	spi_sw(BBREG2, 0x80);	//Set CCA mode to ED

	spi_sw(RSSITHCCA, 0x60);//ED threshold for CCAs

	spi_sw(SLPACK, 0x5f);	//20Mhz clock recovery time

	spi_sw(BBREG6, 0x40);	// Append RSSI value in Rx packets

//	spi_sw(SECCR1, 0x08);	// Enable Sniffer mode to get Rx Packet time stamp (unit=1/8us). Note: Disable this when using the 16-bit half-symbol timer.

	spi_lw(RFCTRL1, 0x01);	// UZ2400 Discrepancy Notes 002, rev. 1.1: 1. Optimal tuning option for RF performance

	spi_lw(RFCTRL2, 0x80);	//RF-PLL Control

	spi_lw(RFCTRL6, 0x90);	//RF optimized control

	spi_lw(RFCTRL7, 0x80);	//Sleep clock selection, [6:7] = 10 : use internal ring oscillator

	spi_lw(RFCTRL8, 0x10);	// RF VCO control

	spi_lw(SCLKDIV, 0x01);	//Sleep clock frequency control

	spi_sw(INTMSK, 0);	//Enable the Interrupt

	//Errata Issue
	spi_sw(FFOEN, 0x98);	// Increase TXON time

	spi_sw(TXPEMISP, 0x95);	// VCO calibration period

	reset_RF_state_machine();

	// 2007/11/21 17:39, Sunny: enable PA control by default, disable PA control if GPIO2 (RXEN) is grounded.
	UzEnablePA();
	spi_sw(GPIO, 0);		// latch PAD status
	if((spi_sr(GPIO) & 0x04) == 0)	// GPIO2 (RXEN) is grounded
		UzDisablePA();
}

/**************************************************************
	Function Name: UzEnablePA()
	Description: Enable Power Amplifier (UP2202)
	Parameters: None
	Return Value: None
**************************************************************/
void UzEnablePA(void)
{
	TRACE_puts("UzEnablePA");

	spi_lw(TESTMODE,  spi_lr(TESTMODE) | 0x07);
	UzSetTxPower(-10);		// UZ2400 TX power = -10 dBm, for better EVM on UP2202
}

/**************************************************************
	Function Name: UzDisablePA()
	Description: Disable Power Amplifier (UP2202)
	Parameters: None
	Return Value: None
**************************************************************/
void UzDisablePA(void)
{
	TRACE_puts("UzDisablePA");

	spi_lw(TESTMODE,  spi_lr(TESTMODE) & ~0x07);
	UzSetTxPower(0);		// UZ2400 TX power = 0 dBm
}

/**************************************************************
	Function Name:  UzSetTxPower()
	Description: Set Tx Power Level (Using data in DS-2400-02 v0.6)
	Parameters: dBm -> Power Level
	Return Value: None
**************************************************************/
void UzSetTxPower(INT8 dB)	// dB Range: 0 ~ -40
{
#if 1
	UINT16 Value;

	TRACE_puts("UzSetTxPower");

	if(dB < 0)
		dB = -dB;
	Value = dB * 100 + 62;
	if((INT16)Value >= 4000)
		Value = 3999;
	else if((INT16)Value < 0)
		Value = 0;

	spi_lw(RFCTRL3, (UINT8)(((Value / 1000) * 8) | ((Value % 1000) / 125)) * 8);
#else
	UINT8 Value = 0x00;
	INT8 Operator = 0x00;

	TRACE_puts("UzSetTxPower");

	if(dB > 40 || dB < 0)
		return;

	if(dB == 0){ //Maximum Tx Power
		Value = 0;
	}else{
		if((Operator = dB - 40) >=0){ //dB = 40
			Value |= 0xc0;
			spi_lw(RFCTRL3, Value); //Set Power
			Value &= 0x00;
			Value |=0x40;
		}else if((Operator = dB - 30) >=0){//30 <= dB < 40
			Value |= 0xc0;
		}else if((Operator = dB - 20) >=0){//20 <= dB < 30
			Value |= 0x80;
		}else if((Operator = dB - 10) >=0){//10 <= dB < 20
			Value |= 0x40;
		}else{                                            // 0 < dB < 10
			Operator = dB;
		}

		if(Operator != 0){
			if(Operator == 1){
				Value |= 0x08;
			}else if(Operator == 2 || Operator == 3){
				Value |= 0x10;
			}else if(Operator == 4){
				Value |= 0x18;
			}else if(Operator == 5){
				Value |= 0x20;
			}else if(Operator == 6){
				Value |= 0x28;
			}else if(Operator == 7){
				Value |= 0x30;
			}else{//Operator == 8 or 9
				Value |= 0x38;
			}
		}
	}

	spi_lw(RFCTRL3, Value);
#endif
}

/**************************************************************
	Function Name: UzSetChannel()
	Description: Set Channel
	Parameters: NewChannel -> Logical Channel you want modify, Value Range 11~26
	Return Value: None
**************************************************************/

void UzSetChannel(UINT8 NewChannel){
	TRACE_printf(("UzSetChannel=%d", (UINT16)NewChannel));

	if (NewChannel > 26 || NewChannel < 11)
		return; //Check Channel Range

	// 2007/12/21 17:00, Sunny: make sure that RF is not in the TX mode. ==> wait until RX state
	while(spi_lr(RFSTATE) != RF_STATE_RX);

	spi_lw(RFCTRL0, ((NewChannel - 11) << 4) + 0x02); // Shift logic channel, Program Channel

	reset_RF_state_machine();
}

/**************************************************************
	Function Name: UzReadRSSI()
	Description: Read current RSSI value
	Parameters: None
	Return Value: RSSI Value
**************************************************************/

UINT8 UzReadRSSI(void)
{
	UINT8 rssi;

	TRACE_puts("UzReadRSSI=");

	// 2006/7/7 13:52, UBEC Joseph: prepare to read RSSI value
	spi_sw(BBREG2, 0x00);

#if 0
	spi_sw(BBREG6, spi_sr(BBREG6) | 0x80); // Issue RSSI Request

	while(!(spi_sr(BBREG6) & 0x1)); //Wait Value Ready
#else
	// 2006/5/15 12:08, UBEC Joseph: read RSSI
	//	write SREG 0x3E: 0xC0 ==> wait SREG 0x3E become 0x41 ==> read RSSI
	//	SREG 0x3E bit7: trigger
	//		  bit6: calculate RSSI
	//		  bit0: ready
	spi_sw(BBREG6, 0xC0);

	while(!(spi_sr(BBREG6) != 0x41)); //Wait Value Ready
#endif

	rssi = spi_lr(RSSI);

	// 2006/7/7 13:52, UBEC Joseph: after read RSSI value
	spi_sw(BBREG2, 0x80);

	DBG_printf(("0x%02X%", (UINT16)rssi));

	return(rssi);
}

/**************************************************************
	Function Name: UzSetMacAddress()
	Description: Set Mac Address
	Parameters: MacAddress -> 64bits Mac Address Pointer
	Return Value: None
	Note: Mac Address is used as the hardware filter of RX Normal Mode
**************************************************************/

void UzSetMacAddress(UINT8 *MacAddress){
	UINT8 i;

	TRACE_puts("UzSetMacAddress [");

	for (i=8; i--; ) {
		DBG_printf(("%02X%c", (UINT16)*(MacAddress+i), i ? ':' : ']'));
		spi_sw(EADR0+i, *(MacAddress+i)); //Set Value
	}
}

/**************************************************************
	Function Name: UzSetPanId()
	Description: Set Pan Id
	Parameters: PanId -> 16bits PAN identifier
	Return Value: None
	Note: Pan Id is used as the hardware filter of RX Normal Mode
**************************************************************/

void UzSetPanId(UINT16 PanId){
	UINT8 i;

	TRACE_printf(("UzSetPanId=%d (0x%04X)", PanId, PanId));

	SWAPINT16(&PanId);
	for(i=0; i<2; i++)
		spi_sw(PANIDL+i, *(((UINT8 *)&PanId)+i)); //Set Value
}

/**************************************************************
	Function Name: UzSetNwkAddr()
	Description: Set Network(16bits) Address
	Parameters: NwkAddr -> 16bits short Address
	Return Value: None
**************************************************************/

void UzSetNwkAddr(UINT16 NwkAddr){
	UINT8 i;

	DBG_printf((", NwkAddr=%u (0x%04x)", NwkAddr, NwkAddr));

	SWAPINT16(&NwkAddr);
	for(i=0; i<2; i++)
		spi_sw(SADRL+i, *(((UINT8 *)&NwkAddr)+i)); //Set Value

}

/**************************************************************
	Function Name: UzSoftReset()
	Description: Reset UZ2400 by Software
	Parameters: None
	Return Value: None
**************************************************************/

void UzSoftReset(void)
{
	TRACE_puts("UzSoftReset");

	//Soft Reset: use 0x03, if use 0x07 then should wait circuit stability
	//Reset Power management, Base band, Mac
	spi_sw(SOFTRST, 0x07);

#ifdef IOUZ2410
    #ifdef UZ2410_VERSION_2
	// 2007/7/23 16:37, Sunny: walk around UZ2410-v2 RF reset bug: end the reset state by reading XDATA
	ACC = *(XUINT8 *)0x0000;
	*(XUINT8 *)0x0000 = ACC;
    #endif // #ifdef UZ2410_VERSION_2

	// 2007/8/8 16:27, Sunny: restore MCU clock after RF reset.
    #if (CPU_CLOCK == 20000000L)
	spi_lw(0x24D, 0x0);	/* Set MCU Clock = 20MHz */
    #endif
#endif // #ifdef IOUZ2410

	do {
		spi_lw(TXBASE, 0x55);	// test ready
	} while(spi_lr(TXBASE) != 0x55);	// RF chip not ready
	do {
		spi_lw(TXBASE, 0xAA);	// test ready again
	} while(spi_lr(TXBASE) != 0xAA);	// RF chip not ready
}

/**************************************************************
	Function Name:
	Description:
	Parameters: None
	Return Value: None
**************************************************************/

void UzSetCoordinator(){
	TRACE_puts("UzSetCoordinator");

    	spi_sw(RXMCR, spi_sr(RXMCR) |0x0c); //Set the PAN coordinator Bit
}

/**************************************************************
	Function Name: UzEnabTurboMode()
	Description: Enable The Turbo Mode of UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzEnabTurboMode(void)
{
	TRACE_puts("UzEnabTurboMode");

	spi_sw(BBREG0, spi_sr(BBREG0) | 0x01);

	spi_sw(BBREG3, (spi_sr(BBREG3) & (UINT8)(~0xFE)) | 0x38);

	spi_sw(BBREG4, (spi_sr(BBREG4) & (UINT8)(~0xFC)) | 0x5C);

	reset_RF_state_machine();
}


/**************************************************************
	Function Name: UzDisTurboMode()
	Description: Disable The Turbo Mode of UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzDisTurboMode(void)
{
	TRACE_puts("UzDisTurboMode");

	spi_sw(BBREG0, spi_sr(BBREG0) & ~0x01);

	spi_sw(BBREG3, (spi_sr(BBREG3) & (UINT8)(~0xFE)) | 0xD8);

	spi_sw(BBREG4, (spi_sr(BBREG4) & (UINT8)(~0xFC)) | 0x9C);

	reset_RF_state_machine();
}

/**************************************************************
	Function Name: UzRxOnlyBeacon()
	Description: Let Rx Receive Only IEEE 802.15.4 Beacon Frame
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxOnlyBeacon(void)
{
	TRACE_puts("UzRxOnlyBeacon");

	spi_sw(RXFLUSH, (spi_sr(RXFLUSH) & ~0x0e) | 0x02);
}

/**************************************************************
	Function Name: UzRxAllFrame()
	Description: Let Rx Receive all IEEE 802.15.4 Frame
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxAllFrame(void)
{
	TRACE_puts("UzRxAllFrame");

	spi_sw(RXFLUSH, spi_sr(RXFLUSH) & ~0x0e);
}

/**************************************************************
	Function Name: UzRxFlush()
	Description: Drop data in RXFIFO
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxFlush(void)
{
	TRACE_puts("UzRxFlush");

	spi_sw(RXFLUSH, spi_sr(RXFLUSH) | 0x01);// Trigger drop data
}

/**************************************************************
	Function Name: UzSleep()
	Description: Force UZ2400 into Sleep Mode
	Parameters: None
	Return Value: None
**************************************************************/

void UzSleep(void)
{
	TRACE_puts("UzSleep");

	spi_sw(SLPACK, spi_sr(SLPACK) | 0x80);
}

/**************************************************************
	Function Name: UzTx()
	Description: Send Raw Data
	Parameters: DataPtr -> Out Data Pointer
	            Length -> Out data Length

	Return Value: SUCCESS -> Send Data Successful
	              FAILURE -> Send Data Failure
**************************************************************/

UINT8 UzTx(UINT8 *DataPtr, UINT8 Length, UINT8 mactpye, UINT8 unettpye){

	UINT8 Value, retry_counter;
	struct _child_list_ *ChiPtr;

	if(!((unettpye == 0xff) || UnetSys.Flag.NwkReady)) {
		TRACE_puts("UzTx: UNET network not ready");
		return FAILURE;
	}

	TRACE_printf(("UzTx, Length=%d", (UINT16)Length));

	spi_lw(TX_N_LEN, Length); // Fill Data Length Into TXFIFO

	Endian_Modify(DataPtr,mactpye,unettpye);
	spi_fill_fifo(TX_N_BASE, DataPtr, Length); //Fill Data Into TXFIFO

	retry_counter = 0;

RETRY_ENTRY:
	if(!UnetSys.Flag.JoinNetwork || UnetSys.Flag.Broadcast){
		WaitMS(10 + rand() % 90);	// Random delay for each out-going RF packet.
		UnetSys.Flag.Broadcast = 0;
	}

	TRACE_printf(("UzTx#%d, ", (int)retry_counter));
	Value = spi_sr(TXNMTRIG);
	if(*(DataPtr) & 0x20){
		DBG_puts("AckReq");
		Value |= 0x05; //Set Ackreq(SREG0x1B[2]) if re-transmission is required
	}else{
		DBG_puts("NoAckReq");
		Value = (Value & ~0x04) | 0x01; //Clear Ackreq
	}

	RxTx_LED_On();

#if 1
	if(Value & 0x04) {	// ask ACK
		// 2007/9/12 17:36, Sunny: make sure we clean the RxFIFO to catch the Ack response
		while(IntStatus.Rx) {
			unet_msg_dispatch();
		}

		// 2007/9/12 17:59, Sunny: disable RF Rx path
		// 2007/10/16 modify 0x02->0x04
    		Length = spi_sr(BBREG1) & ~0x04;
    		spi_sw(BBREG1, Length | 0x04);

		// 2007/10/1 13:31, Sunny: flush RxFIFO to confirm nothing left in the RxFIFO to catch the Ack response!
		UzRxFlush();
	}

	IntStatus.TxN = 0; // 2007/8/1 17:10, Sunny: Reset Status before trig Tx.
	spi_sw(TXNMTRIG, Value);  //Set trigger bit(SREG0x1B[0]) to send packet This bit will be automatically cleared.

	if(Value & 0x04) {	// ask ACK
	    	spi_sw(BBREG1, Length);	 // 2007/9/12 17:59, Sunny: enable RF Rx path, we have only 1ms to turn it on before the Rx node tx the Ack packet.
	}
#else
	if(Value & 0x04) {	// ask ACK
		// 2007/9/12 17:36, Sunny: make sure we clean the RxFIFO to catch the Ack response
		while(IntStatus.Rx) {
			unet_msg_dispatch();
		}

		// 2007/10/1 13:31, Sunny: flush RxFIFO to confirm nothing left in the RxFIFO to catch the Ack response!
		UzRxFlush();
	}

	IntStatus.TxN = 0; // 2007/8/1 17:10, Sunny: Reset Status before trig Tx.
	spi_sw(TXNMTRIG, Value);  //Set trigger bit(SREG0x1B[0]) to send packet This bit will be automatically cleared.
#endif

	while(1){
		if(IntStatus.TxN){
		//	IntStatus.TxN = 0; //Reset Status
			RxTx_LED_Off();

		        Value = spi_sr(TXSR);	// UnetSys.IntFlag.TxStatus;
			DBG_printf((", TXSR=%02X, SREG3A=%02X, SREG3F=%02X", (UINT16)Value, (UINT16)spi_sr(0x3a), (UINT16)spi_sr(0x3f)));
			if(!(Value & 0x01)) { //tx success
				return SUCCESS;
			}else{	//tx failure, retry UNET_MAX_RETRY times
				DBG_puts(", TXNFIFO fail");
				if(retry_counter < UNET_MAX_RETRY){
					retry_counter += 1;
//					WaitMS(10 + rand() % 90);
					TRACE_puts("UzTx RETRY");
					goto RETRY_ENTRY;
				}
			}

			//if retry over UNET_MAX_RETRY times, recovery mechanism start.
			if(UnetSys.Flag.JoinNetwork && !UnetSys.Flag.ProcessAssociate){
				Endian_Modify(DataPtr, 0xa, 0xff);
				tx_failure_address = ((UNET_HEADER *)DataPtr)->MHR.DstAddr;

				if((ChiPtr = UnetSys.ChildTail) != NULL) {
			    	do {
						ChiPtr = ChiPtr->Next;
						if(ChiPtr->NetworkAddress == tx_failure_address){
							ChiPtr->tx_failure = 1;
							break;
						}

			    	} while(ChiPtr != UnetSys.ChildTail);
				}
				UnetSys.Flag.TxFailure = 1;
				UnetSys.Flag.PermitJoin = 0;
				TRACE_printf(("tx_failure_address: %04X, ", tx_failure_address));
			}
			break;
		}

	    #if 1
		if(IntStatus.Rx) { //Received a frame
			unet_msg_dispatch();
		}
	    #endif
	}

	DBG_puts(": FAILURE");
	return FAILURE;
}






//jason:08/04/29 add security function 
//security test***************************************************************************** 

/**************************************************************
	Function Name:  UzSecureTx()
	Description: Transmit Secure Data
	Parameters: SecMode -> Encryption Mode
	                   *SecKey -> Security Key, defined by user
	                   *DataPtr -> Data Pointer
	                   Length -> Data Length
	                   HeaderLength -> Length of Data Header	                
	Return Value: SUCCESS -> Send Data Successful
	                     FAILURE -> Send Data Failure 
**************************************************************/


UINT8 UzSecureTx(UINT8 SecMode, UINT8 *SecKey, UINT8 *DataPtr, UINT8 Length, UINT8 mactpye, UINT8 unettpye){

	UINT8 Value, retry_counter;
	struct _child_list_ *ChiPtr;

	if(!((unettpye == 0xff) || UnetSys.Flag.NwkReady)) {
		TRACE_puts("UzTx: UNET network not ready");
		return FAILURE;
	}

	TRACE_printf(("UzTx, Length=%d", (UINT16)Length));

	spi_lw(TX_N_LEN, Length); // Fill Data Length Into TXFIFO

	Endian_Modify(DataPtr,mactpye,unettpye);
	spi_fill_fifo(TX_N_BASE, DataPtr, Length); //Fill Data Into TXFIFO

        spi_fill_fifo(KEY_TX_N, SecKey, 16);//Fill Security key
  
        spi_sw(SECCR0, (spi_sr(SECCR0) & ~0x07) | SecMode); //Fill in cipher mode
  
	retry_counter = 0;

RETRY_ENTRY:
	if(!UnetSys.Flag.JoinNetwork || UnetSys.Flag.Broadcast){
		WaitMS(10 + rand() % 90);	// Random delay for each out-going RF packet.
		UnetSys.Flag.Broadcast = 0;
	}

	TRACE_printf(("UzTx#%d, ", (int)retry_counter));
	Value = spi_sr(TXNMTRIG);
	if(*(DataPtr) & 0x20){
		DBG_puts("AckReq");
		Value |= 0x05; //Set Ackreq(SREG0x1B[2]) if re-transmission is required
	}else{
		DBG_puts("NoAckReq");
		Value = (Value & ~0x04) | 0x01; //Clear Ackreq
	}

	RxTx_LED_On();

#if 1
	if(Value & 0x04) {	// ask ACK
		// 2007/9/12 17:36, Sunny: make sure we clean the RxFIFO to catch the Ack response
		while(IntStatus.Rx) {
			unet_msg_dispatch();
		}

		// 2007/9/12 17:59, Sunny: disable RF Rx path
		// 2007/10/16 modify 0x02->0x04
    		Length = spi_sr(BBREG1) & ~0x04;
    		spi_sw(BBREG1, Length | 0x04);

		// 2007/10/1 13:31, Sunny: flush RxFIFO to confirm nothing left in the RxFIFO to catch the Ack response!
		UzRxFlush();
	}

	IntStatus.TxN = 0; // 2007/8/1 17:10, Sunny: Reset Status before trig Tx.
	spi_sw(TXNMTRIG, Value);  //Set trigger bit(SREG0x1B[0]) to send packet This bit will be automatically cleared.

	if(Value & 0x04) {	// ask ACK
	    	spi_sw(BBREG1, Length);	 // 2007/9/12 17:59, Sunny: enable RF Rx path, we have only 1ms to turn it on before the Rx node tx the Ack packet.
	}
#else
	if(Value & 0x04) {	// ask ACK
		// 2007/9/12 17:36, Sunny: make sure we clean the RxFIFO to catch the Ack response
		while(IntStatus.Rx) {
			unet_msg_dispatch();
		}

		// 2007/10/1 13:31, Sunny: flush RxFIFO to confirm nothing left in the RxFIFO to catch the Ack response!
		UzRxFlush();
	}

	IntStatus.TxN = 0; // 2007/8/1 17:10, Sunny: Reset Status before trig Tx.
	spi_sw(TXNMTRIG, Value);  //Set trigger bit(SREG0x1B[0]) to send packet This bit will be automatically cleared.
#endif

	while(1){
		if(IntStatus.TxN){
		//	IntStatus.TxN = 0; //Reset Status
			RxTx_LED_Off();

		        Value = spi_sr(TXSR);	// UnetSys.IntFlag.TxStatus;
			DBG_printf((", TXSR=%02X, SREG3A=%02X, SREG3F=%02X", (UINT16)Value, (UINT16)spi_sr(0x3a), (UINT16)spi_sr(0x3f)));
			if(!(Value & 0x01)) { //tx success
				return SUCCESS;
			}else{	//tx failure, retry UNET_MAX_RETRY times
				DBG_puts(", TXNFIFO fail");
				if(retry_counter < UNET_MAX_RETRY){
					retry_counter += 1;
//					WaitMS(10 + rand() % 90);
					TRACE_puts("UzTx RETRY");
					goto RETRY_ENTRY;
				}
			}

			//if retry over UNET_MAX_RETRY times, recovery mechanism start.
			if(UnetSys.Flag.JoinNetwork && !UnetSys.Flag.ProcessAssociate){
				Endian_Modify(DataPtr, 0xa, 0xff);
				tx_failure_address = ((UNET_HEADER *)DataPtr)->MHR.DstAddr;

				if((ChiPtr = UnetSys.ChildTail) != NULL) {
			    	do {
						ChiPtr = ChiPtr->Next;
						if(ChiPtr->NetworkAddress == tx_failure_address){
							ChiPtr->tx_failure = 1;
							break;
						}

			    	} while(ChiPtr != UnetSys.ChildTail);
				}
				UnetSys.Flag.TxFailure = 1;
				UnetSys.Flag.PermitJoin = 0;
				TRACE_printf(("tx_failure_address: %04X, ", tx_failure_address));
			}
			break;
		}

	    #if 1
		if(IntStatus.Rx) { //Received a frame
			unet_msg_dispatch();
		}
	    #endif
	}

	DBG_puts(": FAILURE");
	return FAILURE;
}



/**************************************************************
	Function Name: UzSecureRx()
	Description: Receive Secure Data
	Parameters: SecMode -> Decryption Mode
	                   *SecKey -> Security Key, defined by user
	                   *InBuff -> Data Buffer Pointer
	Return Value: Length -> Received Data Length
**************************************************************/

UINT8 UzSecureRx(UINT8 SecMode, UINT8 *SecKey, UINT8 *InBuff){
  UINT8 Length;
  
  //if(IntStatus.Sec == 1)
  {
  IntStatus.Sec = 0;
  
  spi_fill_fifo(KEY_RX_N, SecKey, 16);//Fill Secure key into FIFO
  
  spi_sw(SECCR0, (spi_sr(SECCR0) & ~0x38) | SecMode); //Fill cipher mode
  
  //Security start
  spi_sw(SECCR0, spi_sr(SECCR0) | 0x40); // Trigger Security Process 
  
  //Wait Interrupt
  while(1){
    if(IntStatus.Rx == 1){
      spi_rd_rx_fifo(InBuff, (UINT8)&Length); //Fetch Data from RXFIFO
      IntStatus.Rx =0; //Reset Interrupt Flag
      return Length;
      }
    }		
  }
  
  return 0;
}

//end security test***********************************************************************************


// ************************************************************************************************
// ************************************************************************************************
volatile INTERRUPT_STS IntStatus;

#pragma message (__LOC__ "UzGetIntStatus() is called by interrupt service routine.")
#if defined(__C51__)
#pragma NOAREGS
#endif
void UzGetIntStatus(void)
{
#if defined(IOXC800)
	/*Handle saving of RMAP and PAGE*/
	_push_(SYSCON0);
	SYSCON0 &= ~(1 << 0);
	/*Save PORT page and SCU page into ST1 and configure to 0*/ 
	PORT_PAGE = ((0 << 0) | (1 << 4) | (2 << 6));
	SCU_PAGE = 	((0 << 0) | (1 << 4) | (2 << 6));
#endif
	
	//Read the int status
	*((UINT8 *) &IntStatus) |= spi_sr(ISRSTS);

#if defined(IOXC800)
	/*Restore previously stored SFR setting*/
	SCU_PAGE = 	((0 << 0) | (1 << 4) | (3 << 6));
	PORT_PAGE = ((0 << 0) | (1 << 4) | (3 << 6));	
	_pop_(SYSCON0);
#endif
}
